package com.safx.xml;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.List;

import javax.xml.stream.XMLInputFactory;
//import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;

import org.apache.log4j.Logger;


//import com.safx.enity.constants.XMLTestCaseTag;
//import com.safx.entity.Verify;
import com.safx.exception.XpathNotFoundException;
import com.safx.utility.DataProviderTool;
import com.safx.entity.constants.XMLTestDefinitionTag;
import com.safx.entity.tags.ABaseTag;
import com.safx.entity.tags.AnnotationTag;
import com.safx.entity.tags.Function;
import com.safx.entity.tags.Html;
import com.safx.entity.tags.TestCaseTag;
import com.safx.entity.tags.TestDefinitionTag;
import com.safx.entity.tags.TestStepsTag;
import com.safx.entity.tags.TestsTag;
import com.safx.entity.tags.Verify;

public class XML2TestDefinition {
	private static Logger logger = Logger.getLogger(XML2TestDefinition.class);
	private static XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
	private static XMLStreamReader xmlStreamReader;
	private static String fileName;

	/**
	 * <b> </b>
	 * @Author Aaron Lin, 1-31-2012
	 */
	public static List<TestDefinitionTag> xml2TestDefinitionTag(List<File> files) {
		List<TestDefinitionTag> list = new ArrayList<TestDefinitionTag>();
		for (File file : files) {
			list.add(xml2TestDefinitionTag(file));
		}
		return list;
	}
	
	/**
	 * <b> parse TestDefinition.xml file to TestDefinition Object</b>
	 * @Author Aaron Lin, 1-31-2012
	 */
	private static TestDefinitionTag xml2TestDefinitionTag(File file) {
		TestDefinitionTag td = new TestDefinitionTag();
		try{
			xmlStreamReader = xmlInputFactory.createXMLStreamReader(new FileReader(file));
		//	td = new TestDefinitionTag();
			while(xmlStreamReader.hasNext()){
				int eventType = xmlStreamReader.getEventType();
				switch(eventType){
					case XMLStreamReader.START_ELEMENT:
						String localName = xmlStreamReader.getLocalName();
						if(localName.equals(XMLTestDefinitionTag.ANNOTATION)){
								td.setAnnotationTag(xml2AnnotationTag());
						}else if(localName.equals(XMLTestDefinitionTag.TESTS)){
								td.setTestsTag(xml2TestsTag());
						}
					case XMLStreamReader.END_ELEMENT:
						break;
					default:
						break;
				}
				// get the next event 
				xmlStreamReader.next();
			}
		}
		catch(FileNotFoundException e){
			logger.error(e.getMessage(), e);
		}
		catch(XMLStreamException e){
			logger.error(e.getMessage(), e);
		}
		return td;
	}
	
	/**
	 * Parse xml Annotation Tag to Annotation Object
	 * @author Aaron Lin 1-31-2012
	 */
	private static AnnotationTag xml2AnnotationTag() throws XMLStreamException{
		AnnotationTag at = new AnnotationTag();
		while(xmlStreamReader.getEventType() != XMLStreamReader.END_ELEMENT  || xmlStreamReader.getLocalName() != XMLTestDefinitionTag.ANNOTATION){
			int eventType = xmlStreamReader.getEventType();			
			switch(eventType){
				case XMLStreamReader.START_ELEMENT:
					String localName = xmlStreamReader.getLocalName();
					if(localName.equals(XMLTestDefinitionTag.DESCRIPTION)){
						at.setDescription(xmlStreamReader.getElementText());
					}else if(localName.equals(XMLTestDefinitionTag.CREATED)){
						at.setCreatedAuthor(xmlStreamReader.getAttributeValue(null,XMLTestDefinitionTag.AUTHOR));
						at.setCreatedDate(xmlStreamReader.getAttributeValue(null,XMLTestDefinitionTag.DATE));
					}else if(localName.equals(XMLTestDefinitionTag.LASTUPDATED)){
						at.setLastUpdatedAuthor(xmlStreamReader.getAttributeValue(null,XMLTestDefinitionTag.AUTHOR));
						at.setLastUpdatedDate(xmlStreamReader.getAttributeValue(null,XMLTestDefinitionTag.DATE));
					}
				case XMLStreamReader.END_ELEMENT:
					break;		
				default:
					break;
			}
			//get the next event
			xmlStreamReader.next();
		}
		return at;
	}
	
	/**
	 * Parse xml Tests Tag to Tests Object
	 * @author Aaron Lin 1-31-2012
	 */
	private static TestsTag xml2TestsTag() throws XMLStreamException{
		TestsTag testsTag = new TestsTag();
		while(xmlStreamReader.getEventType()!= XMLStreamReader.END_ELEMENT || xmlStreamReader.getLocalName()!= XMLTestDefinitionTag.TESTS){
			int eventType = xmlStreamReader.getEventType();
			switch(eventType){
			case XMLStreamReader.START_ELEMENT:
				String localName = xmlStreamReader.getLocalName();
				if(localName.equals(XMLTestDefinitionTag.TESTCASE)){
					testsTag.getTestCaseTagList().add(xml2TestCaseTag());
				}
			case XMLStreamReader.END_ELEMENT:
				break;		
			default:
				break;
		}
			//get the next event
			xmlStreamReader.next();
		}
		return testsTag;
	}
	
	/**
	 * Parse xml TestCase Tag to TestCase Object
	 * @author Aaron Lin 1-31-2012
	 */
	private static TestCaseTag xml2TestCaseTag() throws XMLStreamException{
		TestCaseTag testCaseTag = new TestCaseTag();
		while(xmlStreamReader.getEventType()!= XMLStreamReader.END_ELEMENT || xmlStreamReader.getLocalName()!= XMLTestDefinitionTag.TESTCASE){
			int eventType = xmlStreamReader.getEventType();
			switch(eventType){
			case XMLStreamReader.START_ELEMENT:
				String localName = xmlStreamReader.getLocalName();
				if(localName.equals(XMLTestDefinitionTag.TESTCASE)){
					testCaseTag.setAnnotationTag(xml2AnnotationTag());
				}else if(localName.equals(XMLTestDefinitionTag.TESTSTEPS)){
					testCaseTag.setTestStepsTag(xml2TestStepsTag());
				}
			case XMLStreamReader.END_ELEMENT:
				break;
			default:
				break;
			}
			//get the next event
			xmlStreamReader.next();
		}
		return testCaseTag;
	}
	
	/**
	 * Parse xml TestSteps Tag to TestSteps Object
	 * @author Aaron Lin 1-31-2012
	 */
	private static TestStepsTag xml2TestStepsTag() throws XMLStreamException{
		TestStepsTag testStepsTag = new TestStepsTag();
		while(xmlStreamReader.getEventType()!= XMLStreamReader.END_ELEMENT || xmlStreamReader.getLocalName()!= XMLTestDefinitionTag.TESTSTEPS){
			int eventType = xmlStreamReader.getEventType();
			switch(eventType){
			case XMLStreamReader.START_ELEMENT:
				String localName = xmlStreamReader.getLocalName();
				if(localName.equals(XMLTestDefinitionTag.HTML)){
					testStepsTag.addTestStep(xml2Html());
				}else if(localName.equals(XMLTestDefinitionTag.FUNCTION)){
					testStepsTag.addTestStep(xml2Function());
				}else if(localName.equals(XMLTestDefinitionTag.VERIFY)){
					testStepsTag.addTestStep(xml2Verify());
				}
			case XMLStreamReader.END_ELEMENT:
				break;
			default:
				break;
			}
			//get the next event
			xmlStreamReader.next();
		}
		return testStepsTag;
	}

	/**
	 * Parse xml Html Tag to Html Object
	 * @author Aaron Lin 1-31-2012
	 */
	private static ABaseTag xml2Html() throws XMLStreamException{
		Html html = new Html();
		html.setCommand(xmlStreamReader.getAttributeValue(null, XMLTestDefinitionTag.COMMAND));

		try {
			String target = xmlStreamReader.getAttributeValue(null, XMLTestDefinitionTag.TARGET);
			String value = xmlStreamReader.getAttributeValue(null, XMLTestDefinitionTag.VALUE);
			html.setTarget(DataProviderTool.getData(target));
			html.setValue(DataProviderTool.getData(value));
		} catch (XpathNotFoundException e) {
			logger.error("file: " + fileName + " line: " + xmlStreamReader.getLocation().getLineNumber() + " " + e.getMessage(), e);
		}
		html.setLineNumb(xmlStreamReader.getLocation().getLineNumber());
		while (xmlStreamReader.getEventType() != XMLStreamReader.END_ELEMENT) {
			int eventType = xmlStreamReader.getEventType();
			//String localName = xmlStreamReader.getLocalName();
			switch(eventType){
			case XMLStreamReader.START_ELEMENT:
				if (eventType == XMLStreamConstants.CHARACTERS) {
					if (xmlStreamReader.isWhiteSpace()) {
						html.setInfo("");
					} else {
						html.setInfo(xmlStreamReader.getText());
					}
					break;
				} else if (xmlStreamReader.hasNext()) {
					//get next event
					xmlStreamReader.next();
				}
			case XMLStreamReader.END_ELEMENT:
				break;
			default:
				break;
			}
		}
		return html;
	}
	
	/**
	 * Parse xml Function Tag to Function Object
	 * @author Aaron Lin 1-31-2012
	 */
	private static ABaseTag xml2Function() throws XMLStreamException{
		Function function = new Function();
		function.setCommand(xmlStreamReader.getAttributeValue(null, XMLTestDefinitionTag.COMMAND));

		try {
			function.setTarget(DataProviderTool.getData(xmlStreamReader.getAttributeValue(null, XMLTestDefinitionTag.TARGET)));
			function.setValue(DataProviderTool.getData(xmlStreamReader.getAttributeValue(null, XMLTestDefinitionTag.VALUE)));
		} catch (XpathNotFoundException e) {
			logger.error("file: " + fileName + " line: " + xmlStreamReader.getLocation().getLineNumber() + " " + e.getMessage(), e);
		}
		function.setLineNumb(xmlStreamReader.getLocation().getLineNumber());
		while (xmlStreamReader.getEventType() != XMLStreamReader.END_ELEMENT) {
			int eventType = xmlStreamReader.getEventType();
			//String localName = xmlStreamReader.getLocalName();
			switch(eventType){
			case XMLStreamReader.START_ELEMENT:
				if (eventType == XMLStreamConstants.CHARACTERS) {
					if (xmlStreamReader.isWhiteSpace()) {
						function.setInfo("");
					} else {
						function.setInfo(xmlStreamReader.getText());
					}
					break;
				} else if (xmlStreamReader.hasNext()) {
					//get next event
					xmlStreamReader.next();
				}
			case XMLStreamReader.END_ELEMENT:
				break;
			default:
				break;
			}
		}
		return function;
	}
	
	/**
	 * Parse xml Verify Tag to Verify Object
	 * @author Aaron Lin 1-31-2012
	 */
	private static Verify xml2Verify() throws XMLStreamException{
		Verify verify = new Verify();
		try {
			verify.setExcepted(DataProviderTool.getData(xmlStreamReader.getAttributeValue(null, XMLTestDefinitionTag.EXPECTED)));
		} catch (XpathNotFoundException e) {
			logger.error("file: " + fileName + " line: " + xmlStreamReader.getLocation().getLineNumber() + " " + e.getMessage(), e);
		}
//		verify.setAvt(getAVT(xmlStreamReader.getAttributeValue(null, XMLTestCaseTag.TYPE)));
		Boolean flag = true;
		while (xmlStreamReader.hasNext() && flag) {
			switch (xmlStreamReader.getEventType()) {
			case XMLStreamReader.START_ELEMENT:
				verify.setLineNumb(xmlStreamReader.getLocation().getLineNumber());
				String name = xmlStreamReader.getLocalName();
				if (name.equals(XMLTestDefinitionTag.HTML)) {
//					verify.setVerify(xml2Html());
				} else if (name.equals(XMLTestDefinitionTag.FUNCTION)) {
//					verify.setVerify(xml2Function());
				} else if (name.equals(XMLTestDefinitionTag.VERIFY)) {
				} else {
					logger.debug("xml2Verify unhandle tag: " + name);
				}
				break;
			case XMLStreamReader.END_ELEMENT:
				if (xmlStreamReader.getLocalName().equals(XMLTestDefinitionTag.VERIFY)) {
					flag = false;
				}
				break;
			default:
				break;
			}
			if (xmlStreamReader.hasNext()) {
				xmlStreamReader.next();
			}// 获取下一个解析事件
		}
		verify.setInfo(verify.getVerify().getInfo());
		return verify;
	}
}
